<template>
  <el-dialog v-bind="getBindValue" v-model="modelValueRef">
    <template #header="{ close, titleId, titleClass }" v-if="!$slots.title">
      <div :class="`${prefixCls}-header`">
        <ModalHeader :helpMessage="getProps.helpMessage" :title="getMergeProps.title" :id="titleId" :class="titleClass"
          @dblclick="handleTitleDbClick"></ModalHeader>
        <ModalClose :canFullscreen="getProps.canFullscreen" :fullScreen="fullScreenRef" @cancel="close"
          @fullscreen="handleFullScreen" :titleId="titleId" :titleClass="titleClass" />
      </div>
    </template>
    <template #footer v-if="!$slots.footer">
      <ModalFooter  v-bind="getProps" @cancel="handleCancel" @ok="handleOk"></ModalFooter>
    </template>
    <ModalWrapper ref="modalWrapperRef" :fullScreen="fullScreenRef" :loading="getProps.loading"
      :loading-tip="getProps.loadingTip" :minHeight="getProps.minHeight" :height="getWrapperHeight"
      :useWrapper="getProps.useWrapper" @height-change="handleHeightChange" :model-value="modelValueRef">
      <slot></slot>
    </ModalWrapper>

    <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import { omit } from 'lodash-es';
import { computed, getCurrentInstance, ref, toRef, unref, useAttrs, watchEffect } from 'vue';
import { basicProps } from './props';
import { ModalMethods, ModalProps } from './typing';
import { Recordable } from '/#/global';
import { deepMerge } from '@/utils';
import { useDesign } from '@/hooks/web/useDesign';
import ModalHeader from './components/ModalHeader.vue'
import ModalFooter from './components/ModalFooter.vue';
import ModalClose from './components/ModalClose.vue';
import ModalWrapper from './components/ModalWrapper.vue'
import { useFullScreen } from './hooks/useModalFullScreen';
import { isFunction } from '@/utils/is';

const { prefixCls } = useDesign('basic-modal')


const emit = defineEmits<{
  (e: 'register', modalMethod: ModalMethods, uuid: string): void
  (e: 'ok'): void,
  (e: 'height-change', realHeight: number): void,
  (e: 'cancel'): void
}>()

const props = defineProps(basicProps)
console.log(props)
const attrs = useAttrs()
const modelValueRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null);

// Custom title component: get title
const getMergeProps = computed((): Recordable => {
  return {
    ...props,
    ...(unref(propsRef) as any)
  };
});


const modalWrapperRef = ref<any>(null);

// modal   Bottom and top height
const extHeightRef = ref(0);

const { handleFullScreen, getWrapClassName, fullScreenRef } = useFullScreen({
  modalWrapperRef,
  extHeightRef,
  wrapClassName: toRef(getMergeProps.value, 'wrapClassName'),
});

const getWrapperHeight = computed(() => {
  if (unref(fullScreenRef)) return undefined;
  return unref(getProps).height;
});

watchEffect(() => {
  modelValueRef.value = !!props.modelValue;
  fullScreenRef.value = !!props.fullscreen;
})
/**
 * @description: 设置modal参数
 */
function setModalProps(props: Partial<ModalProps>): void {
  // Keep the last setModalProps
  propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
  if (Reflect.has(props, 'modelValue')) {
    modelValueRef.value = !!props.modelValue
  }
  if (Reflect.has(props, 'fullscreen')) {
    fullScreenRef.value = !!props.fullscreen;
  }
}

// modal component does not need title and origin buttons
const getProps = computed((): Recordable => {
  const opt = {
    ...unref(getMergeProps),
    modelValue: unref(modelValueRef),
    okButtonProps: undefined,
    cancelButtonProps: undefined,
    title: undefined
  };
  return {
    ...opt,
  };
});
const modalMethods: ModalMethods = {
  setModalProps,
  emitVisible: undefined,
};

const instance = getCurrentInstance();
if (instance) {
  emit('register', modalMethods, instance.uid + '');
}

const getBindValue = computed((): Recordable => {
  let attr = {
    ...attrs,
    modelValue: unref(modelValueRef),
    ...unref(getMergeProps),
    fullscreen: unref(fullScreenRef)
  }
  // scrollTop, centered, cancelText, okText, canFullscreen, height, minHeight, closeFunc

  return omit(attr, ['title', 'scrollTop', 'centered', 'cancelText', 'okText', 'canFullscreen', 'height', 'minHeight', 'closeFunc', 'confirmLoading', 'useWrapper', 'showOkBtn'
    , 'showCancelBtn', 'loading', 'loadingTip', 'helpMessage', 'modalHeaderHeight','okType','cancelButtonProps', 'okButtonProps']);
})

function handleTitleDbClick() {
  if (!props.canFullscreen) return;
  handleFullScreen();
}
function handleHeightChange(height: number) {
  emit('height-change', height);
}

async function handleCancel() {
  if (props.closeFunc && isFunction(props.closeFunc)) {
    const isClose: boolean = await props.closeFunc();
    modelValueRef.value = !isClose;
    return;
  }
  modelValueRef.value = false
  emit('cancel')
}
function handleOk() {
  emit('ok')
}
</script>

<style lang="scss">
.gm-basic-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;

  .gm-basic-title {
    position: relative;
    display: flex;
    padding-left: 7px;
    font-size: 16px;
    font-weight: 500;
    line-height: 24px;
    color: rgba(0, 0, 0, 0.85);
    cursor: pointer;
  }
}
</style>